package com.scorpio.server.inter;

import com.scorpio.api.Config;
import com.scorpio.baen.UserInfo;
import com.scorpio.server.base.BaseIMServer;
import com.scorpio.server.base.MessagePullProcessor;
import com.scorpio.utils.ClientManager;
import com.shooter.utils.PrintUtil;
import com.shooter.utils.StringUtil;
import com.scorpio.api.ServiceApi;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.scorpio.api.Config.ENCODING;

public class TCPProtocolImpl implements TCPProtocol {
    NetworkMsgObserver msgObserver;
    // 缓冲区大小
    public static final int bufferSize = 1024 * 10;
    public static Charset charset = Charset.forName(Config.ENCODING);

    public TCPProtocolImpl(NetworkMsgObserver msgObserver) {
        this.msgObserver = msgObserver;
    }

    @Override
    public void handleAccept(SelectionKey key) {
        // 获得与客户端通信的信道
        try {
            // 返回创建此键的通道，接受客户端建立连接的请求，并返回 SocketChannel 对象
            SocketChannel client = ((ServerSocketChannel) key.channel()).accept();
            // 非阻塞式
            client.configureBlocking(false);
            // 注册到selector
            client.register(key.selector(), SelectionKey.OP_READ);
            UserInfo user = new UserInfo(client);
            ClientManager.getInstance().addClinet(client, user);
            msgObserver.doNewConnect(client, user);
        } catch (IOException e) {
            e.printStackTrace();
            key.cancel();
        }
    }

    @Override
    public void handleRead(SelectionKey key) {
        // 获得与客户端通信的信道
        SocketChannel client = (SocketChannel) key.channel();
        try {
            // 得到并清空缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
            // 读取信息获得读取的字节数
            long bytesRead = client.read(buffer);
            if (bytesRead == -1) {//没有读取到内容的情况
                buffer.clear();
            } else {
                buffer.flip();
                msgObserver.doNetworkMessage(client, ClientManager.getInstance().getClinet(client), charset.decode(buffer).toString());
                buffer.clear();
                // 设置为下一次读取或是写入做准备
                key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            //断开连接
            msgObserver.doDisConnect(client, ClientManager.getInstance().getClinet(client));
            ClientManager.getInstance().removeClinet(client);
            key.cancel();
        }
    }

    @Override
    public void handleWrite(SelectionKey key) {
        SocketChannel client = (SocketChannel) key.channel();
        try {
            String returnMsg = msgObserver.doSendMessage(client, ClientManager.getInstance().getClinet(client));
            if (StringUtil.checkStringNoNull(returnMsg)) {
                returnMsg += MessagePullProcessor.MSG_END;
                client.write(charset.encode(returnMsg));
            }
        } catch (IOException e) {
            e.printStackTrace();
            msgObserver.doDisConnect(client, ClientManager.getInstance().getClinet(client));
            ClientManager.getInstance().removeClinet(client);
            key.cancel();
        }
    }
}
